<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>
<script src="../underscore1.9.1.js"></script>
<!-- <script src="../underscore-1.8.3-analysis.js"></script> -->
<script>
    // 【1】Array.prototype.sort
    var students = [{
        name: 'wxj',
        age: 18
    }, {
        name: 'john',
        age: 14
    }, {
        name: 'bob',
        age: 23
    }];
    var sortedStudents = students.sort(function(left, right) {
        return right.age < left.age;
    });
    // => sortStudents: [
    // {name: 'john', age: 14},
    // {name: 'wxj', age: 18},
    // {name: 'bob', age: 23},
    //]

    //【2】 _.sorted
    // _.sortedBy(obj, iteratee) ： 根据比较条件 ieratee ，对 obj 进行排序
    // 源码：
    _.sortBy = function(obj, iteratee, context) {
        var index = 0;
        iteratee = cb(iteratee, context);
        // 先通过map生成新的对象集合,该对象提供了通过iteratee计算后的值, 方便排序
        // [{value:1,index:0,criteria: sin(1)}, ...]
        // 再排序.sort
        // 最后再通过pluck把值摘出来
        return _.pluck(_.map(obj, function(value, key, list) {
            return {
                value: value,
                index: index++,
                criteria: iteratee(value, key, list)
            };
        }).sort(function(left, right) {
            var a = left.criteria;
            var b = right.criteria;
            if (a !== b) {
                if (a > b || a === void 0) return 1;
                if (a < b || b === void 0) return -1;
            }
            return left.index - right.index;
        }), 'value');
    };
    // 下面解释一下 _.sortBy 的工作流程：
    // 通过 _.map 生成一个新的集合，该集合的每个元素是一个对象，他具有三个属性：
    // value ： 元素值
    // index ： 索引位置
    // criteria ：排序准则，该准则将通过被优化的 iteratee 计算得到。underscore 看到了元素间的比较仍将落脚到“值比较”的本质
    // 假设我们现在有集合
    var students = [{
        name: 'wxj',
        age: 18
    }, {
        name: 'john',
        age: 14
    }, {
        name: 'bob',
        age: 23
    }];
    // 假设我们需要按照年龄进行排序，那么传入的 iteratee 为：
    var iteratee = function(value, key, index, elem) {
        return elem.age;
    };
    // 经过该过程，该集合将变为：
    var newStudents = [{
        value: {
            name: 'wxj',
            age: 18
        },
        index: 0,
        criteria: 18
    }, {
        value: {
            name: 'john',
            age: 14
        },
        index: 0,
        criteria: 14
    }, {
        value: {
            name: 'bob',
            age: 23
        },
        index: 0,
        criteria: 23
    }];
    // 利用 Array.prototype.sort 以及我们确定的排序准则 criteria 对新生成的集合进行排序：
    var sortedStudents = newStudents.sort(function(left, right) {
        var a = left.criteria;
        var b = right.criteria;
        if (a !== b) {
            if (a > b || a === void 0) return 1;
            if (a < b || b === void 0) return -1;
        }
        return left.index - right.index;
    });
    // => sortedStudents: [
    // {
    // value: {name: 'john', age: 14},
    // index: 0,
    // criteria: 14
    // },
    // {
    // value: {name: 'wxj', age: 18},
    // index: 0,
    // criteria: 18
    // },
    // {
    // value: {name: 'bob', age: 23},
    // index: 0,
    // criteria: 23
    // }
    //];
    // 再通过 _.pluck 取出 value 属性，过滤掉不需要的 index 及criteria 属性：
    var ret = _.pluck(sortedStudents, 'value');
    // => ret: [
    // {name: 'john', age: 14},
    // {name: 'wxj', age: 18},
    // {name: 'bob', age: 23},
    //]
    // 最后，我们看一看 _.sortBy 带来的便捷性:
    var students = [{
        name: 'wxj',
        age: 18
    }, {
        name: 'john',
        age: 14
    }, {
        name: 'bob',
        age: 23
    }];
    var sortedStudents = _.sortBy(students, 'age');
    // => sortStudents: [
    // {name: 'john', age: 14},
    // {name: 'wxj', age: 18},
    // {name: 'bob', age: 23},
    //]
</script>

</html>